package com.hsl.housaileibot001.controller;

import cn.tbox.sdk.core.exception.TboxClientConfigException;
import cn.tbox.sdk.core.exception.TboxHttpResponseException;
import cn.tbox.sdk.model.file.File;
import cn.tbox.sdk.model.file.FileType;
import cn.tbox.sdk.model.request.ChatRequest;
import cn.tbox.sdk.model.response.SyncChatResponse;
import cn.tbox.sdk.model.response.TboxResponse;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hsl.housaileibot001.ai.bailing.BailingChatService;
import com.hsl.housaileibot001.common.Result;
import com.hsl.housaileibot001.document.MockQuestion;
import com.hsl.housaileibot001.model.InterviewQuestion;
import com.hsl.housaileibot001.model.MockExamGenerationTask;
import com.hsl.housaileibot001.model.dto.BailingChatRequestDTO;
import com.hsl.housaileibot001.model.dto.BailingGenerateMockExamDTO;
import com.hsl.housaileibot001.model.dto.MockExamGenerationMessage;
import com.hsl.housaileibot001.model.vo.MockExamVO;
import com.hsl.housaileibot001.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 白凌相关接口
 *
 * @author liul
 */
@Tag(name = "白凌接口", description = "白凌相关接口")
@RestController
@RequestMapping("/bailing")
@RequiredArgsConstructor
public class BailingController {

    private final BailingChatService bailingChatService;
    private final MockQuestionService mockQuestionService;
    private final UserService userService;
    private final InterviewQuestionService interviewQuestionService;
    private final MockExamGenerationTaskService taskService;
    private final MockExamGenerationProducerService producerService;
    private final OkHttpClient okHttpClient;
    
    @Value("${bailing.app-id}")
    private String bailingAppId;
    
    @Value("${bailing.api-token:}")
    private String bailingApiToken;

    @Operation(summary = "非流式聊天测试", description = "调用白凌接口进行非流式聊天测试")
    @PostMapping("/chat")
    public Result<SyncChatResponse> chat(@Valid @RequestBody BailingChatRequestDTO requestDTO) {
        try {
            SyncChatResponse response = bailingChatService.chat(requestDTO);
            return Result.success(response);
        } catch (TboxClientConfigException | TboxHttpResponseException e) {
            return Result.error("调用白凌聊天接口失败：" + e.getMessage());
        }
    }

    @Operation(summary = "文件流式聊天", description = "支持单个文件上传的流式聊天接口")
    @PostMapping(value = "/stream-chat-with-files", produces = "text/event-stream")
    public void streamChatWithFiles(
            @Parameter(description = "应用ID") @RequestParam String appId,
            @Parameter(description = "用户查询") @RequestParam String query,
            @Parameter(description = "用户ID") @RequestParam String userId,
            @Parameter(description = "会话ID") @RequestParam(required = false) String conversationId,
            @Parameter(description = "上传的文件") @RequestParam(value = "file", required = false) MultipartFile uploadedFile) {
        try {
            // 上传文件到服务器并获取文件 ID
            List<File> files = new ArrayList<>();
            if (uploadedFile != null && !uploadedFile.isEmpty()) {
                // 使用 TboxClient 的 uploadFile 方法上传文件
                String tempFilePath = saveTempFile(uploadedFile);
                try {
                    TboxResponse<String> uploadResponse = bailingChatService.uploadFile(tempFilePath);
                    String fileId = uploadResponse.getData();
                    
                    // 根据 MIME type 判断文件类型
                    String contentType = uploadedFile.getContentType();
                    FileType fileType = determineFileType(contentType);
                    
                    File file = new File(fileId, fileType);
                    files.add(file);
                } finally {
                    // 删除临时文件
                    java.io.File tempFile = new java.io.File(tempFilePath);
                    if (tempFile.exists()) {
                        tempFile.delete();
                    }
                }
            }

            // 构建 ChatRequest
            ChatRequest chatRequest = new ChatRequest(appId, query, userId, conversationId);
            chatRequest.setFiles(files);
            chatRequest.setStream(true);

            // 调用流式聊天服务
            bailingChatService.streamChatWithFiles(chatRequest);
        } catch (Exception e) {
            throw new RuntimeException("流式聊天失败：" + e.getMessage(), e);
        }
    }

    /**
     * 根据 MIME type 判断文件类型
     * @param contentType MIME type
     * @return FileType 枚举值
     */
    private FileType determineFileType(String contentType) {
        if (contentType == null) {
            return FileType.FILE;
        }
        
        String lowerType = contentType.toLowerCase();
        
        // 判断图片类型
        if (lowerType.startsWith("image/")) {
            return FileType.IMAGE;
        }
        
        // 判断音频类型
        if (lowerType.startsWith("audio/")) {
            return FileType.AUDIO;
        }
        
        // 判断视频类型
        if (lowerType.startsWith("video/")) {
            return FileType.VIDEO;
        }
        
        // 默认为通用文件
        return FileType.FILE;
    }

    /**
     * 保存上传的文件到临时目录
     * @param multipartFile 上传的文件
     * @return 临时文件路径
     */
    private String saveTempFile(MultipartFile multipartFile) throws Exception {
        String tempDir = System.getProperty("java.io.tmpdir");
        String fileName = UUID.randomUUID() + "_" + multipartFile.getOriginalFilename();
        String filePath = tempDir + java.io.File.separator + fileName;
        
        java.io.File tempFile = new java.io.File(filePath);
        multipartFile.transferTo(tempFile);
        
        return filePath;
    }

    @Operation(summary = "生成模拟题", description = "使用白凌接口生成结构化模拟题")
    @PostMapping("/generate-mock-exam")
    public Result<MockExamVO> generateMockExam(
            @Parameter(description = "面试题ID") @RequestParam Long interviewQuestionId,
            @Parameter(description = "用户需求描述") @RequestParam String userMessage) {
        try {
            // 先检查 MongoDB 中是否已经有该面试题的模拟题
            List<MockQuestion> existingQuestions = mockQuestionService.findActiveByInterviewQuestionId(interviewQuestionId);
            
            MockExamVO mockExam;
            
            if (existingQuestions != null && !existingQuestions.isEmpty()) {
                // 如果已经有模拟题，直接返回缓存的数据
                mockExam = new MockExamVO();
                mockExam.setInterviewQuestionId(interviewQuestionId);
                mockExam.setMockQuestions(existingQuestions.stream()
                        .map(MockQuestion::toVO)
                        .collect(Collectors.toList()));
            } else {
                // 如果没有缓存，调用白凌接口生成模拟题
                // 从登录信息中获取用户ID
                String userId = String.valueOf(userService.getCurrentUser().getId());
                
                // 构建请求DTO
                BailingGenerateMockExamDTO requestDTO = new BailingGenerateMockExamDTO();
                requestDTO.setAppId(bailingAppId);
                requestDTO.setUserId(userId);
                requestDTO.setUserMessage(userMessage);
                
                mockExam = bailingChatService.generateMockExam(requestDTO);
                mockExam.setInterviewQuestionId(interviewQuestionId);
                
                // 保存模拟题到 MongoDB
                if (mockExam.getMockQuestions() != null && !mockExam.getMockQuestions().isEmpty()) {
                    for (MockExamVO.MockQuestion mockQuestionVO : mockExam.getMockQuestions()) {
                        try {
                            // 创建MongoDB文档实体，直接使用VO对象
                            MockQuestion mockQuestion = new MockQuestion(interviewQuestionId, mockQuestionVO);
                            
                            // 保存到 MongoDB
                            mockQuestionService.save(mockQuestion);
                        } catch (Exception e) {
                            // 记录错误但不中断整个流程
                            System.err.println("保存模拟题到MongoDB失败: " + e.getMessage());
                        }
                    }
                }
            }
            
            return Result.success(mockExam);
        } catch (Exception e) {
            return Result.error("生成模拟题失败：" + e.getMessage());
        }
    }

    @Operation(summary = "批量生成模拟题", description = "根据标签批量生成模拟题（异步）")
    @PostMapping("/batch-generate-mock-exam")
    public Result<String> batchGenerateMockExam(
            @Parameter(description = "标签，多个标签用逗号分隔") @RequestParam String tags) {
        try {
            // 从登录信息中获取用户ID
            Long userId = userService.getCurrentUser().getId();
            String userIdStr = String.valueOf(userId);
            
            // 查询所有匹配标签的题目
            Page<InterviewQuestion> page = new Page<>(1, 500);
            interviewQuestionService.pageWithSearch(page, null, tags);
            List<InterviewQuestion> questions = page.getRecords();
            
            if (questions == null || questions.isEmpty()) {
                return Result.error("未找到匹配标签的题目");
            }
            
            // 创建任务
            String taskId = UUID.randomUUID().toString();
            MockExamGenerationTask task = new MockExamGenerationTask();
            task.setTaskId(taskId);
            task.setUserId(userId);
            task.setTags(tags);
            task.setTotalCount(questions.size());
            task.setCompletedCount(0);
            task.setFailedCount(0);
            task.setStatus("PENDING");
            taskService.createTask(task);
            
            // 构建消息列表并发送到 Kafka
            List<MockExamGenerationMessage> messages = new ArrayList<>();
            for (InterviewQuestion question : questions) {
                MockExamGenerationMessage message = new MockExamGenerationMessage();
                message.setTaskId(taskId);
                message.setInterviewQuestionId(question.getId());
                message.setAppId(bailingAppId);
                message.setUserId(userIdStr);
                message.setUserMessage(question.getTitle());
                message.setTimestamp(System.currentTimeMillis());
                messages.add(message);
            }
            
            // 批量发送消息
            producerService.sendBatchMessages(messages);
            
            return Result.success(taskId);
        } catch (Exception e) {
            return Result.error("创建批量生成任务失败：" + e.getMessage());
        }
    }

    @Operation(summary = "查询任务状态", description = "查询批量生成任务的状态")
    @GetMapping("/task-status/{taskId}")
    public Result<MockExamGenerationTask> getTaskStatus(
            @Parameter(description = "任务ID") @PathVariable String taskId) {
        try {
            MockExamGenerationTask task = taskService.getTaskById(taskId);
            if (task == null) {
                return Result.error("任务不存在");
            }
            
            // 检查任务是否完成
            if ("PROCESSING".equals(task.getStatus())) {
                int total = task.getTotalCount();
                int completed = task.getCompletedCount();
                int failed = task.getFailedCount();
                
                if (completed + failed >= total) {
                    // 所有消息已处理完成
                    if (failed == 0) {
                        taskService.completeTask(taskId);
                    } else {
                        taskService.updateTaskStatus(taskId, "COMPLETED");
                    }
                    task = taskService.getTaskById(taskId);
                }
            }
            
            return Result.success(task);
        } catch (Exception e) {
            return Result.error("查询任务状态失败：" + e.getMessage());
        }
    }
}


